/**
* @describe  音频管理
* @author 游金宇(KM)
* @date 2023-08-03 17:54:31
*/
import { AudioClip, director, log, Node } from 'cc';

import { AudioEffect } from './AudioEffect';
import { AudioMusic } from './AudioMusic';

import { BaseManager } from '../manager/BaseManager';
import { AudioEventConstant } from '../constant/AudioEventConstant';
import { Manager } from '../manager';


/** 
 * 音频管理
 */
export class AudioManager extends BaseManager {
    local_data: any = {};

    private music: AudioMusic;
    private effect: AudioEffect;

    private _volume_music: number = 1;
    private _volume_effect: number = 1;

    private _switch_music: boolean = true;
    private _switch_effect: boolean = true;

    private local_store_key = 'game_audio';

    extra: { [key: string]: any } = {}

    constructor(cat: Manager) {
        super(cat);

        this.local_store_key = this.cat.audio_local_store_key

        var node = new Node('UIAudioManager');
        director.addPersistRootNode(node);

        var music = new Node('UIMusic');
        music.parent = node;
        this.music = music.addComponent(AudioMusic).initAudio(cat)

        var effect = new Node('UIEffect');
        effect.parent = node;
        this.effect = effect.addComponent(AudioEffect).initAudio(cat)

        this.load()
    }

    /**
     * 设置背景音乐播放完成回调
     * @param callback 背景音乐播放完成回调
     */
    setMusicComplete(callback: Function | null = null) {
        this.music.onComplete = callback;
    }


    /**
     * 播放背景音乐
     * @param url        资源地址
     * @param callback   音乐播放完成事件
     */
    async playMusic(url: string): Promise<void>;
    async playMusic(bundleName: string, url: string): Promise<void>;
    async playMusic(arg1: string, arg2?: string): Promise<void> {
        this.music.loop = true;

        let url: string;
        let bundleName: string | undefined;

        if (arg2 !== undefined) {
            bundleName = arg1;
            url = arg2;
        } else {
            url = arg1;
        }

        if (!url.length) return;

        await (bundleName ? this.music.load(bundleName, url) : this.music.load(url)).then(() => {
            if (this._switch_music) {
                this.music.play();
            }
        })
    }

    /**
     * 停止音乐
     */
    stopMusic() {
        if (this.music.state != 0) this.music?.stop();
    }
    /**暂停音乐 */
    pauseMusic() {
        if (this.music.state == 1) this.music?.pause();
    }
    /**恢复音乐 */
    resumeMusic() {
        if ([0, 2].includes(this.music.state)) this.music?.play();
    }
    /**
     * 获取背景音乐播放进度
     */
    get progressMusic(): number {
        return this.music.progress;
    }
    /**
     * 设置背景乐播放进度
     * @param value     播放进度值
     */
    set progressMusic(value: number) {
        this.music.progress = value;
    }

    /**
     * 获取背景音乐音量
     */
    get volumeMusic(): number {
        return this._volume_music;
    }
    /**
     * 设置背景音乐音量
     * @param value     音乐音量值
     */
    set volumeMusic(value: number) {
        this._volume_music = value;
        this.music.volume = value;
    }

    /**
     * 获取背景音乐开关值
     */
    get switchMusic(): boolean {
        return this._switch_music;
    }
    /**
     * 设置背景音乐开关值
     * @param value     开关值
     */
    set switchMusic(value: boolean) {
        log('设置背景音乐开关值', value, this._switch_music)
        if (value == this._switch_music) return
        this._switch_music = value;
        value ? this.resumeMusic() : this.pauseMusic();
        const nonce = value ? AudioEventConstant.MUSIC_ON : AudioEventConstant.MUSIC_OFF
        this.cat.event.emit(nonce)
        this.save();
    }

    /**
     * 播放音效
     * @param url  资源地址
     */
    async playEffect(url: string): Promise<void>;
    async playEffect(bundleName: string, url: string): Promise<void>;
    async playEffect(arg1: string, arg2?: string): Promise<void> {
        if (!this._switch_effect) return

        let url: string;
        let bundleName: string | undefined;

        if (arg2 !== undefined) {
            bundleName = arg1;
            url = arg2;
        } else {
            url = arg1;
        }

        if (!url.length) return

        await (bundleName ? this.effect.load(bundleName, url) : this.effect.load(url)).then(() => {
            this.effect.play();
        })

    }
    /**
     * 停止音效
     */
    stopEffect() {
        this.effect?.stop();
    }

    /**
     * 获取音效音量
     */
    get volumeEffect(): number {
        return this._volume_effect;
    }
    /**
     * 设置获取音效音量
     * @param value     音效音量值
     */
    set volumeEffect(value: number) {
        this._volume_effect = value;
        this.effect.volume = value;
    }

    /**
     * 获取音效开关值
     */
    get switchEffect(): boolean {
        return this._switch_effect;
    }
    /**
     * 设置音效开关值
     * @param value     音效开关值
     */
    set switchEffect(value: boolean) {
        if (value == this._switch_effect) return
        this._switch_effect = value;
        value ? this.effect?.play() : this.effect?.stop();

        const nonce = value ? AudioEventConstant.EFFECT_ON : AudioEventConstant.EFFECT_OFF
        this.cat.event.emit(nonce)

        this.save();
    }

    /** 恢复当前暂停的音乐与音效播放 */
    resumeAll() {
        this.switchMusic && this.music?.play();
        this.switchEffect && this.effect?.play();
    }
    /** 暂停当前音乐与音效的播放 */
    pauseAll() {
        this.music?.pause();
        this.effect?.pause();
    }

    /** 停止当前音乐与音效的播放 */
    stopAll() {
        this.music?.stop();
        this.effect?.stop();
    }


    /** 保存音乐音效的音量、开关配置数据到本地 */
    save() {
        this.local_data.volume_music = this._volume_music;
        this.local_data.volume_effect = this._volume_effect;
        this.local_data.switch_music = this._switch_music;
        this.local_data.switch_effect = this._switch_effect;

        this.local_data.extra = this.extra

        let data = JSON.stringify(this.local_data);
        this.cat.storage.set(this.local_store_key, data);
        return this
    }

    /** 本地加载音乐音效的音量、开关配置数据并设置到游戏中 */
    load() {
        try {
            let data = this.cat.storage.get(this.local_store_key);
            this.local_data = JSON.parse(data);
            this._volume_music = this.local_data.volume_music;
            this._volume_effect = this.local_data.volume_effect;
            this._switch_music = this.local_data.switch_music;
            this._switch_effect = this.local_data.switch_effect;

            this.extra = this.local_data.extra
        } catch (e) {
            this.local_data = {};
            this._volume_music = 0.6;
            this._volume_effect = 1.0;
            this._switch_music = true;
            this._switch_effect = true;
            this.extra = {}
        }

        if (this.music) this.music.volume = this._volume_music;
        if (this.effect) this.effect.volume = this._volume_effect;

    }

}

